package com.boilerCloud.dataSource;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.boilerCloud.util.ParameterNameUtils;
import com.fasterxml.jackson.databind.ObjectMapper;

@Aspect
@Component
public class ControllerInterceptor { 
  private static final Logger logger = LoggerFactory.getLogger(ControllerInterceptor.class); 
  private final static ObjectMapper jsonMapper = new ObjectMapper();  
  
 /* @Value("${spring.profiles}") 
  private String env; 
  */
  /** 
   * 定义拦截规则：拦截com.xjj.web.controller包下面的所有类中，有@RequestMapping注解的方法。 
   */
  @Pointcut("execution(* com.boilerCloud.controller..*(..)) and @annotation(org.springframework.web.bind.annotation.RequestMapping)") 
  public void controllerMethodPointcut(){} 
  
  /** 
   * 拦截器具体实现 
   * @param pjp 
   * @return JsonResult（被拦截方法的执行结果，或需要登录的错误提示。） 
   */
  @Around("controllerMethodPointcut()") //指定拦截器规则；也可以直接把“execution(* com.xjj.........)”写进这里 
  public Object Interceptor(ProceedingJoinPoint pjp){ 
  /*  long beginTime = System.currentTimeMillis(); */
    MethodSignature signature = (MethodSignature) pjp.getSignature(); 
    Method method = signature.getMethod(); //获取被拦截的方法 
  //  String methodName = method.getName(); //获取被拦截的方法名 
    
    String classname = method.getDeclaringClass().getName();
    String info = classname.substring(classname.lastIndexOf("."))+ method.getName() + "()";
    logger.info("Before: interceptor name: {}",info); 
    Object[] arguments = pjp.getArgs();;
    printArgs(arguments, method);
  
  
   // logger.info("请求开始，方法：{}", methodName); 
  
    Object result = null;
	try {
		result = pjp.proceed();
	} catch (Throwable e) {
		// TODO Auto-generated catch block
		logger.info("methodName exception: ", e);
	} 
	printResult(result);
    //logger.info("After: result: {}", result);  
    
    return result; 
  
   
  } 
  
  private void printArgs(Object[] args, Method method) {
		//StringBuffer buff = new StringBuffer();
		try {        
           String[] argNames = null;
           try {
              argNames = ParameterNameUtils.getMethodParamNames(method);
           } catch (Exception e) {
              error("获取参数名称异常：", e);
           }
            
          if (args != null) {
          	  String argName = null;
          	  String value = null;
          	  String argTypeName = null;
          	for (int i = 0; i < args.length; i++) {
          		argTypeName = args[i].getClass().getName();
                  if (argNames != null && argNames.length >= i) {
                       argName = argNames[i];
                  }
                  if(argTypeName.contains("Request") || argTypeName.contains("Response") || argTypeName.contains("MultipartFile")){
                  	info("【参数 {}={} 】", argName, argName);
                  	continue;
                  } 
                  if (args[i] != null) {
                  	try {
                           value = jsonMapper.writeValueAsString(args[i]);
                      } catch (Exception e) {
                           error("转换参数 \"{}\" 发生异常：", argName, e);
                      }
                      info("【参数 {}={} 】", argName, value);
                   } else {
                      info("参数 \"{}\"：NULL", argName);
                   }
               }
            }
       } catch (Exception e) {
            error("【接口调用拦截器】打印方法执行参数异常：", e);
   }
   }
		     
	private void printResult(Object result) {
       if (result != null) {
           try {
               info("【返回数据】：({})", jsonMapper.writeValueAsString(result));
          } catch (Exception e) {
              error("返回数据打印异常：", e);
          }
       } else {
           info("【返回数据】：NULL");
       }
   }
	     
   protected final void error(String msg, Object... objects) {
  	 logger.error(msg, objects);
	 }
	 
   protected final void info(String msg, Object... objects) {
  	 logger.info(msg, objects);
   }
  
  /** 
   * 判断一个方法是否需要登录 
   * @param method 
   * @return 
   */
  /*private boolean isLoginRequired(Method method){ 
    if(!env.equals("prod")){ //只有生产环境才需要登录 
      return false; 
    } 
  
    boolean result = true; 
    if(method.isAnnotationPresent(Permission.class)){ 
      result = method.getAnnotation(Permission.class).loginReqired(); 
    } 
  
    return result; 
  } 
  
  //判断是否已经登录 
  private boolean isLogin(HttpServletRequest request) { 
    return true; 
    String token = XWebUtils.getCookieByName(request, WebConstants.CookieName.AdminToken); 
    if("1".equals(redisOperator.get(RedisConstants.Prefix.ADMIN_TOKEN+token))){ 
      return true; 
    }else { 
      return false; 
    }
  } */
} 